﻿using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Vaccination.API.Repositories;
using DotNetHackathon.GBA.ApiCommon;

namespace Vaccination.API.Infrastructure.Repositories
{
    public class VaccinationInfoRepository : IVaccinationInfoRepository
    {
        private readonly VaccinationDbContext _vaccinationDbContext;

        public VaccinationInfoRepository(VaccinationDbContext vaccinationDbContext)
        {
            _vaccinationDbContext = vaccinationDbContext ?? throw new ArgumentNullException(nameof(vaccinationDbContext));
            _vaccinationDbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        }

        public async Task<VaccinationInfo> AddAsync(VaccinationInfo vaccinationInfo)
        {
            var existedVaccinationInfo = await _vaccinationDbContext.VaccinationInfos
                .Where(v => v.UserId == vaccinationInfo.UserId && v.Status == 1)
                .FirstOrDefaultAsync();
            
            if (existedVaccinationInfo != null)
            {
                //已存在预约信息，直接返回
                return existedVaccinationInfo;
            }

            _vaccinationDbContext.Add(vaccinationInfo);

            try
            {
                await _vaccinationDbContext.SaveChangesAsync();
                return vaccinationInfo;
            }
            catch (DbUpdateException ex)
                when ((ex.InnerException as SqlException)?.Number == 2627)
            {
                return (await GetByIdAsync(vaccinationInfo.Id))!;
            }
        }

        public async Task DeleteAsync(Guid vaccineId)
        {
            var vaccinationInfo = await GetByIdAsync(vaccineId);

            if (vaccinationInfo == null)
            {
                return;
            }

            _vaccinationDbContext.VaccinationInfos.Remove(vaccinationInfo);
            await _vaccinationDbContext.SaveChangesAsync();
        }

        public Task<VaccinationInfo?> GetByIdAsync(Guid vaccineId)
        {
            return _vaccinationDbContext.VaccinationInfos
            .Where(o => o.Id == vaccineId)
            .SingleOrDefaultAsync();
        }

        public async Task<(int total, List<VaccinationInfo> vaccinationInfos)> GetByPage(VaccinationPageInput pageInput)
        {
            if (pageInput == null)
            {
                throw new BusinessException("input.isnull", "输入参数不存在");
            }

            var vaccinationInfos = _vaccinationDbContext.VaccinationInfos.AsQueryable();

            if (pageInput.FilterByUserId.HasValue)
            {
                vaccinationInfos = vaccinationInfos.Where(v => v.UserId == pageInput.FilterByUserId.Value);
            }

            if (pageInput.FilterByStatus.HasValue && pageInput.FilterByStatus.Value > 0 && pageInput.FilterByStatus.Value < 4)
            {
                vaccinationInfos = vaccinationInfos.Where(v => v.Status == pageInput.FilterByStatus.Value);
            }

            switch (pageInput.SortColumn?.ToUpper())
            {
                case "VACCINENAME":
                    {
                        var isDesc = pageInput.IsDesc ?? false;
                        vaccinationInfos = isDesc
                              ? vaccinationInfos.OrderByDescending(v => v.VaccineName)
                              : vaccinationInfos.OrderBy(v => v.VaccineName);
                    }
                    break;
                case "CREATEDTIME":
                    {
                        var isDesc = pageInput.IsDesc ?? false;
                        vaccinationInfos = isDesc
                              ? vaccinationInfos.OrderByDescending(v => v.CompletedTime)
                              : vaccinationInfos.OrderBy(v => v.CompletedTime);
                    }
                    break;
                case "COMPLETEDTIME":
                    {
                        var isDesc = pageInput.IsDesc ?? false;
                        vaccinationInfos = isDesc
                              ? vaccinationInfos.OrderByDescending(v => v.CreatedTime)
                              : vaccinationInfos.OrderBy(v => v.CreatedTime);
                    }
                    break;
                default:
                    {
                        var isDesc = pageInput.IsDesc ?? false;
                        vaccinationInfos = isDesc
                              ? vaccinationInfos.OrderByDescending(v => v.BookedTime)
                              : vaccinationInfos.OrderBy(v => v.BookedTime);
                    }
                    break;
            }

            var count = pageInput.RequireTotal 
                ? await vaccinationInfos.CountAsync() : 0;
            var pageIndex = pageInput.PageNumber < 1 ? 1 : pageInput.PageNumber;
            var pageSize = pageInput.PageSize > 0 ? pageInput.PageSize : 10;
            var items = await vaccinationInfos.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();

            return (count, items);
        }

        public Task UpdateAsync(VaccinationInfo vaccineInfo)
        {
            _vaccinationDbContext.Update(vaccineInfo);
            return _vaccinationDbContext.SaveChangesAsync();
        }
    }
}
